/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package me.panpf.sketch.sample.widget.page;

import me.panpf.sketch.sample.ResourceTable;
import me.panpf.sketch.util.TextUtils;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.components.element.VectorElement;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.net.NetManager;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Locale;

/**
 * HintView
 */
public class HintView extends DirectionalLayout {
    Context context;
    private Text textHintLoadingHint;
    private Button buttonHintAction;
    private Text textHintProgress;
    private Text textHintHint;

    public HintView(Context context) {
        this(context, null);
    }

    public HintView(Context context, AttrSet attrSet) {
        this(context, attrSet, "");
    }

    public HintView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        this.context = context;
        init();
    }

    private void init() {
        Component component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_view_hint, this, true);
        textHintLoadingHint = (Text) component.findComponentById(ResourceTable.Id_text_hint_loadingHint);
        buttonHintAction = (Button) component.findComponentById(ResourceTable.Id_button_hint_action);
        textHintProgress = (Text) component.findComponentById(ResourceTable.Id_text_hint_progress);
        textHintHint = (Text) component.findComponentById(ResourceTable.Id_text_hint_hint);

        setVisibility(Component.HIDE);
    }

    private enum Mode {
        LOADING(0), HINT(1);
        private int index;

        private Mode(int index) {
            this.index = index;
        }
    }

    /**
     * loading
     * @param message
     */
    public void loading(String message) {
        textHintLoadingHint.setText(message);
        textHintLoadingHint.setVisibility(TextUtils.isEmpty(message) ? Component.HIDE : Component.VISIBLE);
        setProgress(0, 0);
        setVisibility(Component.VISIBLE);
    }

    /**
     * setProgress
     * @param totalLength
     * @param completedLength
     */
    public void setProgress(int totalLength, int completedLength) {
        if (completedLength <= 0) {
            textHintProgress.setText("");
        } else {
            int ratio = completedLength / totalLength * 100;
            textHintProgress.setText(String.format("%d%%", ratio, Locale.ENGLISH));
        }
    }


    /**
     * 显示提示
     *
     * @param icon        图标ID，如果不想显示图标的话，此参数传-1即可
     *                    *
     * @param hint        提示信息
     *                    *
     * @param button      按钮的名称
     *                    *
     * @param click       按钮的按下事件
     *                    *
     * @param transparent 是否需要让提示视图变成透明的，透明的提示视图将不再拦截事件
     */
    public void hint(int icon, String hint, String button, ClickedListener click, Boolean transparent) {
        Element[] drawables = textHintHint.getAroundElementsRelative();
        Element top = null;
        if (icon > 0) {
            try {
                String mediaPath = getResourceManager().getMediaPath(icon);
                if (mediaPath.endsWith("xml")) {
                    top = new VectorElement(context, icon);
                } else {
                    Resource resource = getResourceManager().getRawFileEntry(mediaPath).openRawFile();
                    ImageSource imageSource = ImageSource.create(resource, null);
                    PixelMap pixelMap = imageSource.createPixelmap(null);
                    top = new PixelMapElement(pixelMap);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotExistException e) {
                e.printStackTrace();
            } catch (WrongTypeException e) {
                e.printStackTrace();
            }
        }
        textHintHint.setAroundElements(drawables[0], top, drawables[2], drawables[3]);


        if (isNotEmpty(hint)) {
            textHintHint.setText(hint);
        } else {
            textHintHint.setText("");
        }

        if (isNotEmpty(button) && click != null) {
            buttonHintAction.setText(button);
            buttonHintAction.setClickedListener(click);
            visibleViewByAlpha(buttonHintAction, true);
        } else {
            buttonHintAction.setText("");
            buttonHintAction.setClickedListener(null);
            buttonHintAction.setVisibility(Component.INVISIBLE);
        }
        setClickable(!transparent);
        setVisibility(Component.VISIBLE);
    }


    /**
     * 显示提示
     *
     * @param iconId              图标ID，如果不想显示图标的话，此参数传-1即可
     * @param hintText            提示信息
     * @param buttonName          按钮的名称
     * @param buttonClickListener 按钮的按下事件
     */
    public void hint(int iconId, String hintText, String buttonName, ClickedListener buttonClickListener) {
        hint(iconId, hintText, buttonName, buttonClickListener, false);
    }

    /**
     * 显示提示
     *
     * @param iconId   图标ID，如果不想显示图标的话，此参数传-1即可
     *                 *
     * @param hintText 提示信息
     */
    public void hint(int iconId, String hintText) {
        hint(iconId, hintText, null, null, false);
    }


    /**
     * 显示提示，默认没有图标、没有按钮、背景不透明
     *
     * @param hintText    提示信息
     *                    *
     * @param transparent 是否需要让提示视图变成透明的，透明的提示视图将不再拦截事件
     */
    public void hint(String hintText, Boolean transparent) {
        hint(-1, hintText, null, null, transparent);
    }

    /**
     * 显示提示
     *
     * @param hintText 提示信息
     */
    public void hint(String hintText) {
        hint(-1, hintText, null, null, false);
    }

    /**
     * 失败
     *
     * @param exception                 失败了
     *                                  *
     * @param reloadButtonClickListener 重新加载按钮点击监听器
     */
    public void failed(Throwable exception, ClickedListener reloadButtonClickListener) {
        hint(ResourceTable.Graphic_ic_error, getCauseByException(context, exception), "重试", reloadButtonClickListener, false);
    }


    /**
     * 空empty
     *
     * @param message message
     */
    public void empty(String message) {
        hint(ResourceTable.Graphic_ic_error, message, null, null, false);
    }

    /**
     * 隐藏
     */
    public void hidden() {
    }

    /**
     * isEmpty
     *
     * @param string
     * @return boolean
     */
    public boolean isEmpty(String string) {
        return string == null || "".equals(string.trim());
    }

    /**
     * isNotEmpty
     *
     * @param string
     * @return boolean
     */
    public boolean isNotEmpty(String string) {
        return !isEmpty(string);
    }

    /**
     * 将给定视图渐渐显示出来（view.setVisibility(View.VISIBLE)），默认的持续时间为DEFAULT_ALPHA_ANIMATION_DURATION
     *
     * @param view       被处理的视图
     *                   *
     * @param isBanClick 在执行动画的过程中是否禁止点击
     */
    public void visibleViewByAlpha(Component view, Boolean isBanClick) {
        visibleViewByAlpha(view, 400L, isBanClick, null);
    }

    /**
     * 将给定视图渐渐显示出来（view.setVisibility(View.VISIBLE)）
     *
     * @param view              被处理的视图
     *                          *
     * @param durationMillis    持续时间，毫秒
     *                          *
     * @param isBanClick        在执行动画的过程中是否禁止点击
     *                          *
     * @param animationListener 动画监听器
     */
    public void visibleViewByAlpha(Component view, Long durationMillis, Boolean isBanClick, AnimationListener animationListener) {
        if (view.getVisibility() != Component.VISIBLE) {
            view.setVisibility(Component.VISIBLE);
            AnimatorProperty animatorProperty = view.createAnimatorProperty();
            animatorProperty.alphaFrom(0).alpha(1).setDuration(durationMillis).setLoopedListener(new Animator.LoopedListener() {
                @Override
                public void onRepeat(Animator animator) {
                    if (animationListener != null) {
                        animationListener.onRepeat(animator);
                    }
                }
            }).setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                    if (isBanClick) {
                        view.setClickable(false);
                    }
                    if (animationListener != null) {
                        animationListener.onStart(animator);
                    }
                }

                @Override
                public void onStop(Animator animator) {

                }

                @Override
                public void onCancel(Animator animator) {

                }

                @Override
                public void onEnd(Animator animator) {
                    if (isBanClick) {
                        view.setClickable(true);
                    }
                    if (animationListener != null) {
                        animationListener.onEnd(animator);
                    }
                }

                @Override
                public void onPause(Animator animator) {

                }

                @Override
                public void onResume(Animator animator) {

                }
            });
            animatorProperty.start();
        }
    }


    /**
     * 将给定视图渐渐隐去最后从界面中移除（view.setVisibility(View.GONE)）
     *
     * @param view              被处理的视图
     *                          *
     * @param durationMillis    持续时间，毫秒
     *                          *
     * @param isBanClick        在执行动画的过程中是否禁止点击
     *                          *
     * @param animationListener 动画监听器
     */
    public void goneViewByAlpha(Component view, Long durationMillis, Boolean isBanClick, AnimationListener animationListener) {
        if (view.getVisibility() != Component.HIDE) {
            view.setVisibility(Component.HIDE);
            AnimatorProperty animatorProperty = view.createAnimatorProperty();
            animatorProperty.alphaFrom(1).alpha(0).setDuration(durationMillis).setLoopedListener(new Animator.LoopedListener() {
                @Override
                public void onRepeat(Animator animator) {
                    if (animationListener != null) {
                        animationListener.onRepeat(animator);
                    }
                }
            }).setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                    if (isBanClick) {
                        view.setClickable(false);
                    }
                    if (animationListener != null) {
                        animationListener.onStart(animator);
                    }
                }

                @Override
                public void onStop(Animator animator) {

                }

                @Override
                public void onCancel(Animator animator) {

                }

                @Override
                public void onEnd(Animator animator) {
                    if (isBanClick) {
                        view.setClickable(true);
                    }
                    if (animationListener != null) {
                        animationListener.onEnd(animator);
                    }
                }

                @Override
                public void onPause(Animator animator) {

                }

                @Override
                public void onResume(Animator animator) {

                }
            });
            animatorProperty.start();
        }
    }

    /**
     * 将给定视图渐渐隐去最后从界面中移除（view.setVisibility(View.GONE)），默认的持续时间为DEFAULT_ALPHA_ANIMATION_DURATION
     *
     * @param view       被处理的视图
     *                   *
     * @param isBanClick 在执行动画的过程中是否禁止点击
     */
    public void goneViewByAlpha(Component view, Boolean isBanClick) {
        goneViewByAlpha(view, 400L, isBanClick, null);
    }

    /**
     * getCauseByException
     *
     * @param context
     * @param exception
     * @return String
     */
    public String getCauseByException(Context context, Throwable exception) {
        String message;
        if (exception == null) {
            message = "网络连接异常【909】";
        } else if (exception instanceof SecurityException) {
            message = "网络连接异常【101】";
        } else if (exception instanceof UnknownHostException) {
            message = "没有网络连接";
        } else if (exception instanceof SocketTimeoutException) {
            message = "网络连接超时";
        } else if (exception instanceof FileNotFoundException) {
            message = "网络连接异常【404】";
        } else {
            message = "网络连接异常【909】";
        }
        return message;
    }

}
